package com.morningstar.flow.flowable.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.extra.spring.SpringUtil;
import com.morningstar.flow.antvX6.common.Assign;
import com.morningstar.flow.flowable.assigne.AssignMultiStrategy;
import com.morningstar.flow.flowable.assigne.AssigneeStrategyHandler;
import com.morningstar.flow.service.FlowNodeInstanceService;
import com.morningstar.flow.service.FlowNodeService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

import static com.morningstar.flow.flowable.assigne.AssigneeStrategy.NO_ASSIGN;
import static com.morningstar.flow.flowable.constants.VariableName.*;

@Slf4j
@Component("multiInstanceHandler")
public class MultiInstanceHandler {

    @Resource
    private FlowNodeService flowNodeService;


    /**
     * 处理执行人
     *
     * @param execution 执行处理器
     * @return 执行人列表
     */
    public List<String> resolveAssignee(DelegateExecution execution) {
        ExecutionEntityImpl entity = (ExecutionEntityImpl) execution;
        Assign assign = flowNodeService.getAssignByDefinitionKey(entity.getProcessDefinitionKey(), entity.getActivityId());
        log.info("resolveAssignee:{} {}", entity.getActivityId(), entity.getProcessDefinitionKey());
        String assignStrategy = assign.getAssignStrategy();
        if (StringUtils.isBlank(assignStrategy)) {
            throw new RuntimeException("审批人策略未设置");
        }
        AssigneeStrategyHandler assigneeStrategyHandler = AssigneeStrategyHandler.getAssigneeStrategyHandler(assignStrategy);
        if (assigneeStrategyHandler == null) {
            throw new RuntimeException("找不到对应审批人策略");
        }
        List<String> assignees = assigneeStrategyHandler.handler(assign, entity);
        if (CollUtil.isNotEmpty(assignees)) {
            return assignees;
        }
        // 没有获取到执行人
        assignees = new ArrayList<>();
        assignees.add(NO_ASSIGN);
        return assignees;
    }


    /**
     * 会签或者或签完成条件检查
     *
     * @param execution
     */
    public boolean completionCondition(DelegateExecution execution) {
        ExecutionEntityImpl entity = (ExecutionEntityImpl) execution;
        log.info("completionCondition:{} {} {}", execution.getId(), execution.getCurrentActivityId(), entity.getProcessDefinitionKey());
        Assign assign = flowNodeService.getAssignByDefinitionKey(entity.getProcessDefinitionKey(), execution.getCurrentActivityId());
        String assignMultiStrategy = assign.getAssignMultiStrategy();
        Object variable = execution.getVariable(NAME_AUDIT);
        Boolean approveResult = Convert.toBool(variable);
        // 实例总数
        int nrOfInstances = (int) execution.getVariable(NR_OF_INSTANCES);
        // 完成的实例数
        int nrOfCompletedInstances = (int) execution.getVariable(NR_OF_COMPLETED_INSTANCES);
        // 或签  只要有一个审批通过即结束该节点  签署结果-根据最后一个审批结果判断
        if (StringUtils.equalsIgnoreCase(assignMultiStrategy, AssignMultiStrategy.SIGN_ANY)) {
            // 或签只要有一个同意即返回 结果
            if (approveResult) {
                return true;
            }
            // 每个审批都通过  则返回true
            return nrOfInstances == nrOfCompletedInstances;
        }
        // 会签  通过百分比
        if (StringUtils.equalsIgnoreCase(assignMultiStrategy, AssignMultiStrategy.SIGN_ALL)) {
            FlowNodeInstanceService flowNodeInstanceService = SpringUtil.getBean(FlowNodeInstanceService.class);
            Integer agree = flowNodeInstanceService.getAgree(execution.getId());
            BigDecimal result = BigDecimal.valueOf(agree).divide(BigDecimal.valueOf(nrOfInstances), 2, RoundingMode.HALF_UP);
            result = result.multiply(new BigDecimal("100"));
            log.info("result:{} {}", result, assign.getAssignMultiPercentage());
            // 通过百分比 立即结束
            if (result.compareTo(BigDecimal.valueOf(assign.getAssignMultiPercentage())) >= 0) {
                execution.setVariable(NAME_AUDIT, true);
                return true;
            }
            // 所有人完成任务 审批不通过
            if (nrOfInstances == nrOfCompletedInstances) {
                execution.setVariable(NAME_AUDIT, false);
                return true;
            }
            // 百分比没有通过 并且任务未完成 则继续
            return false;
        }
        // 顺序签署  签署结果-根据最后一个审批结果判断
        if (StringUtils.equalsIgnoreCase(assignMultiStrategy, AssignMultiStrategy.SIGN_ORDER)) {
            // 只要有一个失败就返回
            if (!approveResult) {
                return true;
            }
            // 每个审批都通过  则返回true
            return nrOfInstances == nrOfCompletedInstances;
        }
        throw new RuntimeException("未知的会签策略");
    }
}
